package aof

import (
	"abdis/interface/database"
	"abdis/interface/datastruct"
	"abdis/redis/protocol"
)

func entityToCmd(key string, entity *database.DataEntity) *protocol.MultiBulkReply {
	if entity == nil {
		return nil
	}
	var bytes [][]byte
	switch val := entity.Data.(type) {
	case []byte:
		bytes = stringToCmd(key, val)
	case datastruct.List:
		bytes = listToCmd(key, val)
	case datastruct.Set:
		bytes = setToCmd(key, val)
	case datastruct.Dict:
		bytes = hashToCmd(key, val)
	}
	return protocol.MakeMultiBulkReply(bytes)
}

func stringToCmd(key string, bytes []byte) [][]byte {
	return [][]byte{
		[]byte("Set"),
		[]byte(key),
		bytes,
	}
}

func listToCmd(key string, list datastruct.List) [][]byte {
	args := make([][]byte, 2+list.Len())
	args[0] = []byte("RPush")
	args[1] = []byte(key)
	i := 2
	list.ForEach(func(key string, val any) bool {
		bytes, ok := val.([]byte)
		if ok {
			args[i] = bytes
			i++
		}
		return true
	})
	return args
}

func setToCmd(key string, set datastruct.Set) [][]byte {
	args := make([][]byte, 2+set.Len())
	args[0] = []byte("SAdd")
	args[1] = []byte(key)
	i := 2
	set.ForEach(func(key string, val any) bool {
		args[i] = []byte(key)
		i++
		return true
	})
	return args
}

func hashToCmd(key string, hash datastruct.Dict) [][]byte {
	args := make([][]byte, 2+hash.Len()*2)
	args[0] = []byte("HMSet")
	args[1] = []byte(key)
	i := 0
	hash.ForEach(func(field string, val interface{}) bool {
		bytes, _ := val.([]byte)
		args[2+i*2] = []byte(field)
		args[3+i*2] = bytes
		i++
		return true
	})
	return args
}
